/**
 * author:Administrator
 * date:2015/7/27
 * desc:TODO
 */

'use strict';
var debugLog = require('./function.js').debugLog;
debugLog('Load O2O: ' + module.id);

let F = require('./function');
let daoDispatcher = require('./dao/article.js');
var logstash = require('../../common/logFlow/logstash.js');

var api = {};
exports.api = api;

api.test = function*() {
  return 'works';
};

/**
 * 添加一篇文章
 * post /o2o_service/article/v1/add
 {
   "uid":"myUid",
   "tid":"aaa",
   "articleContent":"blabla"
 }
 * @param env
 */
api.add = function*(env) {
  let json = {
    uid: env.I.uid,
    tid: env.I.tid,
    articleContent: env.I.articleContent,
    //
    liketimes: 0,//点赞数
    views: 0, // 阅读数
    status: 1 // fresh new post
  };
  let result = yield daoDispatcher.add(json);
  debugLog(result);
};

/**
 * 发表多个
 * post /o2o_service/article/v1/addBatch
 {"list":
    [
    {"uid":"aa",  "tid":"aa",  "articleContent":"aa"},
    {"uid":"bb",  "tid":"bb",  "articleContent":"bb"}
    ]
  }
 * @param env
 */
api.addBatch = function*(env) {
  let list = env.I.list;
  list.forEach(function (item) {
    item.views = 0;
    item.liketimes = 0;
    item.status = 1;
  });
  let result = yield daoDispatcher.addBatch(list);
  return result;
};

/**
 * 删除所有type数据,重建mapping
 * post /o2o_service/article/v1/deleteMapping
 * {}
 * @return  {"acknowledged": true}
 */
api.deleteMapping = function*(env) {
  let result = yield daoDispatcher.deleteMapping();
  return result;
};

/**
 * post /o2o_service/article/v1/createMapping
 * {}
 * @param env
 * @returns {*}
 */
api.createMapping = function*(env) {
  let result = yield daoDispatcher.createMapping();
  return result;
};

/**
 * same to deleteAll
 * post /o2o_service/article/v1/reBuild
 * {}
 * @param env
 * @returns {*}
 */
api.reBuild = function*() {
  let result = yield daoDispatcher.reBuild();
  return result;
};

/**
 * 获取index
 * post /o2o_service/article/v1/index
 * {}
 * @param env
 * @returns {*}
 */
api.index = function*() {
  let result = yield daoDispatcher.index();
  return result;
};

/**
 * 删除文档,如果指定id则删除指定,否则删除全部 article
 * post /o2o_service/article/v1/deleteDoc
 * {"id":"xxx"}
 * @param env
 */
api.deleteDoc = function*(env) {
  let json = null;
  if (env.I.id) {
    json = {id: env.I.id};
  }
  let result = yield daoDispatcher.deleteDoc(json);
  return result;
};

/**
 * 统计article_content字段中的 top(100,eg)项记录
 * post /o2o_service/article/v1/termfreq
 * {"field":"articleContent","top":100}
 *
 * get /api/v1/article/termfreq?top=100
 */
api.termfreq = function*(env) {
  let field = env.I.field || 'articleContent';
  let topNum = env.I.top || 100;
  let result = yield daoDispatcher.termFreq(field, topNum);
  return result;
};

/**
 * 对一个帖子进行词汇统计
 * get /api/v1/article/termvector?tid=491&debug=1
 *
 * post /o2o_service/article/v1/termvector
 * {"tid":"491"}
 * @param env
 */
api.termvector = function*(env) {
  let tid = env.I.tid;
  let debug = env.I.debug !== undefined;
  let result = yield daoDispatcher.termVector({tid: tid, debug: debug});
  return result ? result : F.returnMsg(400, "invalid tid", 3);
};
/**
 * post /o2o_service/article/v1/qsearch
 * {"q":"妈妈","size":100,"from":0}
 *
 * get /api/v2/article/qsearch?q=foo
 * get /api/v2/article/qsearch?q=foo&size=10&from=10
 */
api.qsearch = function*(env) {
  let q = env.I.q;
  let size = env.I.size || 10;
  let from = env.I.from || 0;
  if (q === undefined) {
    return F.returnMsg(400, "must have q", 3);
  }
  let json = {q: q, size: size, from: from};
  debugLog(json);
  let result = yield daoDispatcher.qSearch(json);
  return result;
};


/**
 * post /o2o_service/article/v1/cscore
 * {"q":"宝宝","add":1,"sub":2,"mul":3}
 *
 * get /api/v2/article/cscore?q=foo
 * get /api/v2/article/cscore?q="宝宝"&add=1&sub=2&mul=3
 */
api.cscore = function*(env) {
  let input = env.I;
  let q = input.q;
  if (q === undefined) {
    return F.returnMsg(400, "must have q", 3);
  }
  let add = input.add ? Number(input.add) : 1;
  let sub = input.sub ? Number(input.sub) : 1;
  let mul = input.mul ? Number(input.mul) : 1;
  let json = {q: q, add: add, sub: sub, mul: mul};
  debugLog(json);
  let result = yield daoDispatcher.cScore(json);
  return result;
};

/**
 * 仅供测试 连接池
 * @returns {*}
 */
api.cleanreq = function*() {
  let result = yield daoDispatcher.cleanReq();
  return result;
};

/**
 * 仅供测试 add + logFlow
 * get /api/v1/article/logflow?useract=post
 * post /o2o_service/article/v1/logflow
 */
api.logflow = function*(env) {
  // create a article
  let mockArticle =
  {
    "action": 'post',
    "uid": 999999,
    "vest": 1,
    "tid": Math.floor(Math.random() * 1000000),
    "articleContent": "blabla",
    "cid": 1111,
    "cid2": Math.random() > 0.5 ? 2222 : 3333,
    "timeline": 1440655329962,
    "lastpost": 1440655329962,
    "views": 1,
    "liketimes": 2,
    "status": 1,
    "replies": 11,
    "userreplies": 2,
    "ctype": 1
  };
  let result = {msg: 'ok'};
  logstash.article(mockArticle);
  return result;
};
/**
 * post /api/v1/article/logflow2
 * post /o2o_service/article/v1/logflow2
 * action,
 * uid,
 * vest,
 * tid,
 * articleContent,
 * cid,
 * cid2,
 * ctype,
 * timeline,
 * lastpost,
 * views,
 * liketimes,
 * status,
 * replies,
 * userreplies
 {
     "list": [{...},{...}]
 }
 * @param env
 * @returns {{msg: (*|string|string|__mapping.article|{_all, properties})}}
 */
api.logflow2 = function*(env) {
  let articleList = env.I.list;
  let result = {msg: articleList[0]};
  yield logstash.articleList(articleList);
  return result;
};

/**
 * 自动分类
 * ctype: 0用户分类,1人工,2机器
 * top=5:取排名前5项的结果
 * get /api/v1/article/autocate?ctype=1&top=5&text=blabla
 * post /o2o_service/article/v1/autocate
 * {"ctype":1,"top":5,"content":"宝宝"}
 *
 * @param env
 */
api.autocate = function*(env) {
  debugLog('----router:autocate---');
  let json = {
    ctype: Number(env.I.ctype),
    text: env.I.text,
    top: env.I.top
  };
  let result = yield daoDispatcher.autoCate(json);
  return result;
};


/**
 * tid=123&top=10&policy=text&debug=1
 * text=blabla&top=10&debug=1
 *
 * 根据内容，找相似帖子tid和text必选一个,如果有text则忽略tid
 * tid 源帖id
 * top 返回的帖子数量
 * text 原帖内容
 * policy 相似策略,现在支持 text, term,但term效果不理想
 * debug
 * @param env
 */
api.similar = function*(env) {
  let tid = env.I.tid;
  let text = env.I.text;
  let top = Number(env.I.top || 10);
  let isDebug = env.I.debug !== undefined;
  //let policy = env.I.policy || 'text';
  let policy = env.I.policy || 'term';
  debugLog('tid=' + tid + ', top=' + top + ', policy=' + policy + ', isDebug=' + isDebug + ', text=' + text);

  let analyzeResult = yield this.analyze(env);
  debugLog('analyzeResult: ' + JSON.stringify(analyzeResult));
  if (analyzeResult.err) {
    return F.returnMsg(400, result.err, 3);
  }
  if (policy === 'term') {
    text = analyzeResult.terms.join(',');
  } else {
    text = analyzeResult.text;
  }

  // {q: q, size: size, from: from} 因为有一个原帖,所以要 N=1个
  let similar = yield daoDispatcher.qSearch({
    q: text,
    size: top + !!tid, // 如果有tid,则需要多查询一个,因为会有一个结果是原帖
    from: 0
  });

  let result = [];
  for (let item of similar.hits) {
    let ret = {
      tid: item._source.tid,
      cid: item._source.cid
    };

    if (isDebug) {
      //ret._score = item._score;
      ret.articleContent = item._source.articleContent;
    }

    if (isDebug || Number(item._id) !== tid) {
      result.push(ret);
    }
  }
  return result;
};


/**
 * 获取text、tid对应的文章的词汇分析结果
 * @param env.I = {tid:xx,text:xx,policy:term/text} tid和 text至少有一个,如果有text, 则忽略tid
 * @returns {err:xx, terms:xx, text:xx, termText:xxx}
 */
api.analyze = function *(env) {
  var fields = env.I || env;
  //var policy = fields.policy || 'text';
  var policy = fields.policy || 'term';
  let ret = {err: null, terms: null, text: fields.text};

  if (!ret.text && !fields.tid) {
    ret.err = "error:must have one field : tid or text";
    return ret;
  }

  if (!ret.text && fields.tid) {
    let article = yield daoDispatcher.getById(fields.tid);
    if (!article) {
      ret.err = "tid " + fields.tid + " invalid";
      return ret;
    } else if (article.status == 0) {
      ret.err = "thread  " + fields.tid + " has been deleted";
      return ret;
    } else {
      ret.text = article.articleContent;
    }
  }

  if (ret.text === null || ret.text.trim() === '') {
    ret.err = "content of tid is empty";
    return ret;
  }
  ret.text = ret.text.replace(/\n/g, '');// replcae \n\n with space
  let terms = yield daoDispatcher.analyze(ret.text);
  if (policy === 'term') {
    terms = yield daoDispatcher.wordFilter(terms);
  }
  ret.terms = terms;

  return ret;
};

//{    act:1,  // 根据某个tid，返回ES中类似的内容(不包含tid自己的5个帖子)；
//  tid:id,  // 不检查此tid 对应帖子内容是否有效。
//           //此后参数不传则有默认值
//  replies:n,             Default: 3：n条或以上回复；0 不过滤此项
//  disableVest:n,     Default: 0：1 只返回用户贴；0 不过滤此项，包含马甲贴
//  imgcount:n          Default: 1：1 必须包含图片; 0 不检查是否包含图片
//  views:n                Default: 5： 查看次数n次或以上；0 不检测查看次数
//}
// {act:2,post:'xxxxx'}

/**
 * /o2o_service/article/v1/similar2
 * tid 和 post 至少有一个如果有post,则忽略tid
 * 如果有debug字段，则返回一些debug信息
 * {
    "act": 2,
    "post": "宝宝",
    "replies": 0,
    "disableVest": 0,
    "imgcount": 0,
    "views": 0,
  	"size":3
}
 * @param Env
 */
api.similar2 = function*(Env) {
  try {
    Env.I = yield F.Init(Env, [1, 2]);
    if (Env.I.errors) {
      return F.returnMsg(400, Env.I.errors.msg, Env.I.errors.level);
    }
    let fields = Env.I;
    fields.size = fields.size || 10; // default 10
    //let policy = fields.policy || 'text';
    let policy = fields.policy || 'term';
    let text;
    let opt = {
      tid: fields.tid,
      text: fields.post,
      policy: policy
    };
    let analyzeResult = yield this.analyze(opt);
    debugLog(' [debug] analyzeResult : ' + JSON.stringify(analyzeResult));
    console.log('similar2 analyzeResult : ' + JSON.stringify(analyzeResult));
    if (analyzeResult.err) {
      return F.returnMsg(400, analyzeResult.err, 3);
    }
    if (policy === 'term') {
      text = analyzeResult.terms.join(',');
    } else {
      text = analyzeResult.text;
    }

    //
    var sizeOffset = !Env.I.post + 0; // 不存在post,则表示tid存在,需要多搜索一个
    var searchOpt = {
      text: text,
      replies: Number(fields.replies || 0),
      disableVest: Number(fields.disableVest || 0),
      imgcount: Number(fields.imgcount || 0),
      views: Number(fields.views || 0),
      size: sizeOffset + Number(fields.size || 10),
      fields: ["tid", "uid"]
    };

    if (Env.I.debug !== undefined) {
      searchOpt.fields.push("articleContent");
    }
    console.log('similar2 searchOpt : ' + JSON.stringify(searchOpt));
    let res = yield daoDispatcher.fineSearch(searchOpt);
    let ret = [];
    res.hits.forEach(item => {
      if (Env.I.post || Env.I.debug !== undefined || item._source.tid != Env.I.tid) {
        ret.push(item._source);
      }
    });

    debugLog(' [debug] similar2: ret=' + ret + ',searchOpt=' + JSON.stringify(searchOpt));
    return ret;
  } catch (err) {
    return F.returnMsg(400, "elastic error " + err, 3);
  }
};


